/***************************************************************************
                          utils_sndsvr.c  -  description
                             -------------------
    begin                : Tue Apr 16 2002
    copyright            : (C) 2002 by Liming Xie
    email                : liming_xie@yahoo.com

    MODIFIED BY: Thomas Chang
    DATE: 2004-05-30
    Description:
    1. Add the last parameter "tout" in the SNDSVR_read
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#ifdef linux
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#else
#include "windows/types.h"
#endif

// #include "sysconf.h"
#include "utils_net.h"
// #include "utils_conf.h"
#include "utils_sndsvr.h"

//#define __DEBUG
#include "Trace.h"

HSNDSVR* SNDSVR_open( int device_index, int sample_rate, int channels, int mode )
{
	SNDSVRMSG	msg;
	HSNDSVR*	handle = NULL;
	int		sockfd;
 //	ConfUnit	*conf, *scf;
	int		SoundPort = DEF_SNDPORT;
   	memset( & msg, 0, sizeof(msg) );
	msg.msg_magic = SNDSVRMSGMAGIC;
	msg.msg_size = sizeof(msg);
	msg.mode = mode;
   	msg.device_index = device_index;
	msg.sample_rate = sample_rate;
    	msg.channels = channels;


#if 0
	conf = ConfUnit_new( "ivcore" );
	if ( ConfUnit_load_from( conf, DEFAULT_CONFIGFILE ) == 0 &&
	     (scf=ConfUnit_get_subunit( conf, SECTION_SOUND )) != NULL )
	{
		SoundPort = ConfUnit_get_item_as_int(scf, STR_SNDPORT, DEF_SNDPORT);
	}
#endif

	sockfd = sock_connect( "127.0.0.1", SoundPort );
	if( sockfd > 0 ) {
		if( sock_write(sockfd, & msg, sizeof(msg)) == sizeof(msg) &&
			sock_read_n_bytes(sockfd, & msg, sizeof(msg)) > 0 &&
			msg.msg_magic == SNDSVRMSGMAGIC &&
			msg.msg_size == sizeof(msg) &&
			msg.buf_size > 0 )
		{

			handle = malloc( sizeof(HSNDSVR) );
		    	if( handle )
		    	{
				memset(handle, 0, sizeof(HSNDSVR));
				handle->fd = sockfd;
				memcpy( & handle->msg, & msg, sizeof(msg) );
				TRACE("SNDSVR_open: OK, sockfd = %d\n", sockfd );
			    	return handle;
		    	}
		    	TRACE("SNDSVR_open: handler malloc error!\n" );
		}
		else
			TRACE("SNDSVR_open: server no response or respone error!\n");
		close( sockfd );
	}
	else
		TRACE("SNDSVR_open: socket connection error %d\n", errno );
	return NULL;
}

int SNDSVR_read( HSNDSVR* handle, void* buf, int size, int tout )
{
    int ret;

#if 0
	ret = sock_read_n_bytes(handle->fd, buf, size);
#else
	{
		fd_set set;
		struct timeval val;
		FD_ZERO( & set );
		FD_SET( handle->fd, & set );
		val.tv_sec = 0;
		val.tv_usec = 0;
		if ( tout > 10000 ) val.tv_usec = tout; 	// minimum tout is 10 mini-seconds
		ret = select( handle->fd +1, & set, NULL, NULL, & val );
		if( ret > 0 ) {
			ret = recv( handle->fd, buf, size, MSG_NOSIGNAL );
		} else if ( ret == 0 ) {
			// select time out
		} else {
			// select error
		}
	}
#endif

    if (ret >= 0) {
    	return ret;
    } else
        return -errno;
}

int SNDSVR_write( HSNDSVR* handle, void* buf, int size )
{
    int 		ret;

    ret = send(handle->fd, buf, size, 0);

    if (ret >= 0) {
    	return ret;
    } else
        return -errno;
}

void SNDSVR_close( HSNDSVR* handle )
{
    close( handle->fd );
    free( handle );
}
